package com.example.myproject.hystrix;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import rx.Observable;
import rx.Observer;
import rx.functions.Action1;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class HelloWorldHystrixCommand extends HystrixCommand<String> {
    private final String name;
    public HelloWorldHystrixCommand(String name) {

        //最少配置:指定命令组名(CommandGroup)
        //super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")).andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld")));
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("Commonservice"))
                /* HystrixCommandKey工厂定义依赖名称 */
                .andCommandKey(HystrixCommandKey.Factory.asKey("HystrixCommandKey :CompanyFacade#getCompanyUuid(GetCompanyUuidRequest request)")));
        this.name = name;
    }

    //这里开始就是调用的远程的逻辑
    @Override
    protected String run() {
        // 依赖逻辑封装在run()方法中
        try {
            System.out.println("run--start " + name +",threadname:" + Thread.currentThread().getName());
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "run-end" + name +",thread:" + Thread.currentThread().getName();
    }

    // 超时、异常后执行该方法,超时和异常 都会进这个方法
    //超时怎么判断的
    @Override
    protected String getFallback() {
        return "exception,fallback执行，在这个:"+Thread.currentThread().getName()+"线程中执行。";
    }

    private static void testSynFun1(){
        //每个Command对象只能调用一次,不可以重复调用,
        //重复调用对应异常信息:This instance can only be executed once. Please instantiate a new instance.
        System.out.println("testSynFun1----start,thread:"+ Thread.currentThread().getName());//main
        HelloWorldHystrixCommand helloWorldCommand = new HelloWorldHystrixCommand("method1-syn-hystrix");
        //使用execute()同步调用代码,效果等同于:helloWorldCommand.queue().get();
        String result = helloWorldCommand.execute(); //     return this.queue().get();
        System.out.println("testSynFun1----end=" + result+",thread:"+ Thread.currentThread().getName());//main
    }

    private static void testAsynchronous() throws  Exception{
        System.out.println("testAsynchronous----start,thread:"+ Thread.currentThread().getName());//main
        HelloWorldHystrixCommand helloWorldCommand = new HelloWorldHystrixCommand("method2-Asynchronous-hystrix");
        //异步调用,可自由控制获取结果时机,
        Future<String> future = helloWorldCommand.queue();
        //get操作不能超过command定义的超时时间,默认:1秒
        //超时等待是通过Locksupoort park 时间的；
        String result = future.get(100, TimeUnit.MILLISECONDS);
        System.out.println("testAsynchronous,end=" + result +",thread:"+ Thread.currentThread().getName());//main
    }

    //HystrixCommand observe() 方法是非阻塞的方式运行run()方式
    //run--start ObserveMehtohd,threadname:hystrix-Commonservice-1
    public static void testObserve() {
        /**
         * 返回的是Hot Observable,HotObservable，不论 “事件源” 是否有“订阅者”
         * 都会在创建后对事件进行发布。所以对于Hot Observable的每一个“订阅者”都有
         * 可能从“事件源”的中途开始的，并可能只是看到了整个操作的局部过程
         */
        System.out.println("testObserve:"+Thread.currentThread().getName());
        //blocking
        Observable<String> ho = new HelloWorldHystrixCommand("ObserveMehtohd").observe();
        //System.out.println(ho.toBlocking().single());

//        non-blockking
//        - this is a verbose anonymous inner-class approach and doesn't do assertions
//        完整的生命周期，
//        ho.subscribe(new Observer<String>() {
//            @Override
//            public void onCompleted() {
//                System.out.println("3333==============onCompleted");
//            }
//
//            @Override
//            public void onError(Throwable e) {
//                e.printStackTrace();
//            }
//
//            @Override
//            public void onNext(String s) {
//                System.out.println("`11111111111111=========onNext: " + s);
//            }
//        });
//
//        //部分生命周期
        ho.subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                System.out.println("2222222222222==================call:232323" + s);
            }
        });
    }


    @Test
    public static void testToObservable() {
        /**
         * Cold Observable在没有 “订阅者” 的时候并不会发布时间，
         * 而是进行等待，直到有 “订阅者” 之后才发布事件，所以对于
         * Cold Observable的订阅者，它可以保证从一开始看到整个操作的全部过程。
         */
        Observable<String> co = new HelloWorldHystrixCommand("testToObservable").toObservable();
        System.out.println(co.toBlocking().single());
    }



    /**
     *   //每个Command对象只能调用一次,不可以重复调用,
     *   //重复调用对应异常信息:This instance can only be executed once. Please instantiate a new instance.
     *
     *
     *
     * @param args
     * @throws Exception
     */
    //调用实例
    public static void main(String[] args) throws Exception{
        System.out.println("mainThreadstart=" + Thread.currentThread().getName());
        testToObservable();
        //testAsynchronous();
        System.out.println("mainThread=" + Thread.currentThread().getName());
    }
}
//运行结果: run()方法在不同的线程下执行
// result=Hello Synchronous-hystrix thread:hystrix-HelloWorldGroup-1
// result=Hello Asynchronous-hystrix thread:hystrix-HelloWorldGroup-2
// mainThread=main
////        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("sinai"))
////                        //command配置
////                        .andCommandKey(HystrixCommandKey.Factory.asKey("GetInfoFromSinaiCommand"))
////                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD))
////                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withRequestCacheEnabled(true))
////
////                        //融断器配置
////                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withCircuitBreakerEnabled(true))
////                        .andCommandPropertiesDefaults(
////                                HystrixCommandProperties.Setter().withCircuitBreakerRequestVolumeThreshold(20))
////                        .andCommandPropertiesDefaults(
////                                HystrixCommandProperties.Setter().withCircuitBreakerSleepWindowInMilliseconds(5000))
////                        .andCommandPropertiesDefaults(
////                                HystrixCommandProperties.Setter().withCircuitBreakerErrorThresholdPercentage(50))
////
////                         //ThreadPool配置
////                        .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("GetInfoFromSinaiCommand"))
////                        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10))
////                        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(-1))